package com.version1_3.dao.implement;

import com.SQLGroup.SQLAccess;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mysql.jdbc.Statement;
import com.util.httpRequest.HttpRequest;
import com.util.property.Properties;
import com.version1_3.dao.ActivityDao;
import com.version1_3.dao.SharedMethodDao1_3;
import com.version1_3.dao.SubscriDao1_3;
import com.version1_3.dao.UserDao1_3;
import com.version1_3.model.UserModel;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Created by kuibu on 15/12/25.
 */
@Repository
public class UserDaoImpl13 implements UserDao1_3 {
    private static final Logger LOGGER = Logger.getLogger(UserDaoImpl13.class);

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private SharedMethodDao1_3 sharedMethodDao13;

    @Autowired
    private SubscriDao1_3 subscriDao13;

    @Autowired
    private ActivityDao activityDao;


    /**
     * 用户网页注册
     */
    @Override
    public int htmlRegister(final String telnumber, final String password, final String inviteCode) {
        Map<String, Object> userTelRegion = HttpRequest.getUserTelRegion(telnumber); // 获取手机号码归属地

        KeyHolder key = new GeneratedKeyHolder();
        Date date = new Date();
        jdbcTemplate.update(new PreparedStatementCreator() {

            @Override
            public PreparedStatement createPreparedStatement(Connection conn)
                    throws SQLException {

                PreparedStatement preStatement = conn.prepareStatement(
                        SQLAccess.AddAHtmlUser, Statement.RETURN_GENERATED_KEYS);
                preStatement.setString(1, inviteCode);
                preStatement.setString(2, telnumber);
                preStatement.setString(3, password);
                preStatement.setTimestamp(4, new Timestamp(new Date().getTime()));
                preStatement.setString(5, (String) userTelRegion.get("province"));
                preStatement.setString(6, (String) userTelRegion.get("city"));
                return preStatement;
            }
        }, key);
        return key.getKey().intValue();
    }

    /**
     * 带邀请码注册
     */
    @Override
    public int registerWithInviteCode(final String telnumber, final String password, final String inviteCode, final String uuid) {
        Map<String, Object> userTelRegion = HttpRequest.getUserTelRegion(telnumber); // 获取手机号码归属地

        KeyHolder key = new GeneratedKeyHolder();
        jdbcTemplate.update(new PreparedStatementCreator() {

            @Override
            public PreparedStatement createPreparedStatement(Connection conn)
                    throws SQLException {

                PreparedStatement preStatement = conn.prepareStatement(
                        SQLAccess.AddAUserVersion1_3, Statement.RETURN_GENERATED_KEYS);
                preStatement.setString(1, inviteCode);
                preStatement.setString(2, uuid);
                preStatement.setString(3, telnumber);
                preStatement.setString(4, password);
                preStatement.setTimestamp(5, new Timestamp(new Date().getTime()));
                preStatement.setString(6, (String) userTelRegion.get("province"));
                preStatement.setString(7, (String) userTelRegion.get("city"));
                return preStatement;
            }
        }, key);
        return key.getKey().intValue();
    }

    /**
     * 获取用户邀请码
     */
    @Override
    public String getInviteCode(String telnumber) {
        try {
            Map inviteCodeMap = jdbcTemplate.queryForMap(SQLAccess.SelectUserInviteCodeWithTelVersion1_3, new Object[]{telnumber});
            return (String) inviteCodeMap.get("inviteCode");
        } catch (EmptyResultDataAccessException exception) {
            return null;
        }
    }

    // 1. 更新用户某个一级分类下的关注分类信息(包括三级分类内容和三级分类顺序)
    @Override
    public boolean updateFirstFocus(JSONArray firstFocusJsonArray, int firstType, int userId) {

        String userFocusStr = sharedMethodDao13.getUserFocusStr(userId);

        // 如果在数据库没有查找到用户关注信息
        if (userFocusStr == null) {
            return false;
        }

        JSONArray jsonArray = JSON.parseArray(userFocusStr);

        // 更新用户关注信息
        jsonArray.set(firstType - 2, firstFocusJsonArray);
        return sharedMethodDao13.updateUserFocus(jsonArray.toString(), userId);
    }

    // 2. 登陆用户将主界面上的三级分类置顶
    @Override
    public boolean topThirdType(int thirdType, int firstType, int userId) {

        String userFocusStr = sharedMethodDao13.getUserFocusStr(userId);

        // 如果在数据库没有查找到用户关注信息
        if (userFocusStr == null) {
            LOGGER.error("在数据库中未查询到用户的focusIds");
            return false;
        }

        JSONArray jsonArray = JSON.parseArray(userFocusStr);
        JSONArray firstFocusJsonArray = jsonArray.getJSONArray(firstType - 2);
        top(firstFocusJsonArray, thirdType);
        sharedMethodDao13.updateUserFocus(jsonArray.toString(), userId);

        // 更新用户置顶数据库字段
        String userTopTypeIds = sharedMethodDao13.getUserTopTypeIds(userId);

        if (userTopTypeIds == null) {
            LOGGER.error("在数据库中未查询到用户的topTypeIds");
            return false;
        }

        JSONArray userTopJsonArray = JSON.parseArray(userTopTypeIds);
        JSONArray firstTopTypeIdJsonArray = userTopJsonArray.getJSONArray(firstType - 2);

        if (!firstTopTypeIdJsonArray.contains(thirdType)) {
            firstTopTypeIdJsonArray.add(thirdType);
        } else {
            LOGGER.error("用户已将此分类置顶: thirdTypeId: " + thirdType);
        }

        sharedMethodDao13.updateUserTopTypeIds(userTopJsonArray.toString(), userId);

        return true;
    }

    /**
     * 取消三级分类置顶
     */
    @Override
    public boolean removeTopThirdType(int thirdType, int firstType, int userId) {
        String userTopTypeIds = sharedMethodDao13.getUserTopTypeIds(userId);

        if (userTopTypeIds == null) {
            LOGGER.error("在数据库中未查询到用户的topTypeIds");
            return false;
        }

        JSONArray userTopJsonArray = JSON.parseArray(userTopTypeIds);
        JSONArray firstTopThirdTypeJsonArray = userTopJsonArray.getJSONArray(firstType - 2);

        try {
            firstTopThirdTypeJsonArray.remove(firstTopThirdTypeJsonArray.indexOf(thirdType));
        } catch (ArrayIndexOutOfBoundsException exception) {
            LOGGER.error("取消置顶移除用户置顶分类错误,thirdType: " + thirdType);
        }

        sharedMethodDao13.updateUserTopTypeIds(userTopJsonArray.toString(), userId);
        return true;
    }


    /*
    * 工具类方法
    */

    /**
     * 将List中的置顶元素置顶
     */
    public static void top(JSONArray firstFocusJsonArray, int thirdType) {
        firstFocusJsonArray.remove(firstFocusJsonArray.indexOf(thirdType));
        firstFocusJsonArray.add(0, thirdType);
    }

    @Override
    public boolean updateFocusList(JSONArray jsonArray, int userId) {

        // 直接使用订阅的更新关注信息功能
        return subscriDao13.changeUserFocus(jsonArray, userId);
    }

    /**
     * 用户登陆
     */
    @Override
    public UserModel login(int userId, String telnumber, String password) {
        /*用户信息Map*/
        Map<String, Object> userInfoMap = null;
        UserModel userModel = new UserModel();

        try {
            // 判断用户是否已经有userId,如果有则用userId和userPasswd进行验证否则用userMail和userPasswd进行验证
            if (userId < 0) {
                userInfoMap = jdbcTemplate.queryForMap(SQLAccess.SelectUserInfoWithTelVersion1_3,
                        new Object[]{telnumber, password});
            } else {
                userInfoMap = jdbcTemplate.queryForMap(SQLAccess.SelectUserInfoWithIdAndPasswdVersion1_3, new Object[]{
                        userId, password});
            }
        } catch (EmptyResultDataAccessException exception) {
            // 密码错误,登陆失败,返回null
            LOGGER.error("用户登陆，找不到用户信息(" + "userId: " + userId + "telnumber: " + telnumber + ",password: " + password + ")...");
            return null;
        }

        // 设置userFocusTypeIds数据
        String userFocusTypeIds = (String) userInfoMap.get("userFocusTypeIds");
        String userTopTypeIds = (String) sharedMethodDao13.getUserTopTypeIds((int) userInfoMap.get("userId"));
        JSONArray userFocusTypeIdsJsonArray = JSON.parseArray(userFocusTypeIds);

        // 循环进行设置用户关注信息格式
        for (int i = 0; i < userFocusTypeIdsJsonArray.size(); i++) {
            JSONArray firstTopTypeJsonArray = userFocusTypeIdsJsonArray.getJSONArray(i);

            JSONArray newFirstTopTypeJsonArray = new JSONArray();
            for (int j = 0; j < firstTopTypeJsonArray.size(); j++) {
                int thirdTypeId = firstTopTypeJsonArray.getIntValue(j);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("thirdTypeId", thirdTypeId);
                jsonObject.put("isToped", userTopTypeIds.contains(String.valueOf(thirdTypeId)));
                newFirstTopTypeJsonArray.add(jsonObject);
            }

            userFocusTypeIdsJsonArray.set(i, newFirstTopTypeJsonArray);
        }

        // 设置用户关注分类信息新格式
        userModel.setUserFocusTypeIds(userFocusTypeIdsJsonArray);


        userModel.setUserId((int) userInfoMap.get("userId"));
        userModel.setUserName((String) userInfoMap.get("userName"));
        userModel.setUserPhoto((String) userInfoMap.get("userPhoto"));
        userModel.setUserSex((String) userInfoMap.get("userSex"));
        userModel.setUserCollectedNum((int) userInfoMap.get("userCollectNumber"));
        userModel.setTokenRY((String) userInfoMap.get("tokenRY"));
        userModel.setSchool((String) userInfoMap.get("school"));
        userModel.setSchoolYear((int) userInfoMap.get("schoolYear"));
        userModel.setHeight(((BigDecimal) userInfoMap.get("height")).intValue());
        userModel.setWeight(((BigDecimal) userInfoMap.get("weight")).doubleValue());

        return userModel;
    }


    /**
     * 根据第三方openid获取用户信息 - iOS版本
     */
    @Override
    public UserModel getUserInfo(String openid) {

        /*用户信息Map*/
        Map<String, Object> userInfoMap = null;
        UserModel userModel = new UserModel();

        try {
            userInfoMap = jdbcTemplate.queryForMap(SQLAccess.SelectUserInfoWithThirdPartOpenidIOSVersion, new Object[]{openid});
        } catch (EmptyResultDataAccessException exception) {
            LOGGER.error("根据第三方openid获取用户信息错误,openid: " + openid);
            return null;
        }

        // 设置userFocusTypeIds数据
        String userFocusTypeIds = (String) userInfoMap.get("userFocusTypeIds");
        String userTopTypeIds = (String) sharedMethodDao13.getUserTopTypeIds((int) userInfoMap.get("userId"));
        JSONArray userFocusTypeIdsJsonArray = JSON.parseArray(userFocusTypeIds);

        // 循环进行设置用户关注信息格式
        for (int i = 0; i < userFocusTypeIdsJsonArray.size(); i++) {
            JSONArray firstTopTypeJsonArray = userFocusTypeIdsJsonArray.getJSONArray(i);

            JSONArray newFirstTopTypeJsonArray = new JSONArray();
            for (int j = 0; j < firstTopTypeJsonArray.size(); j++) {
                int thirdTypeId = firstTopTypeJsonArray.getIntValue(j);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("thirdTypeId", thirdTypeId);
                jsonObject.put("isToped", userTopTypeIds.contains(String.valueOf(thirdTypeId)));
                newFirstTopTypeJsonArray.add(jsonObject);
            }

            userFocusTypeIdsJsonArray.set(i, newFirstTopTypeJsonArray);
        }

        // 设置用户关注分类信息新格式
        userModel.setUserFocusTypeIds(userFocusTypeIdsJsonArray);


        userModel.setUserId((int) userInfoMap.get("userId"));
        userModel.setUserName((String) userInfoMap.get("userName"));
        userModel.setUserPhoto((String) userInfoMap.get("userPhoto"));
        userModel.setUserSex((String) userInfoMap.get("userSex"));
        userModel.setUserCollectedNum((int) userInfoMap.get("userCollectNumber"));
        userModel.setTokenRY((String) userInfoMap.get("token"));
        userModel.setSchool((String) userInfoMap.get("school"));
        userModel.setSchoolYear((int) userInfoMap.get("schoolYear"));
        userModel.setHeight(((BigDecimal) userInfoMap.get("height")).intValue());
        userModel.setWeight(((BigDecimal) userInfoMap.get("weight")).doubleValue());

        return userModel;
    }


    /**
     * 根据第三方openid获取用户信息 - Android版本
     */
    @Override
    public UserModel getUserInfoAnroid(String openid) {

        /*用户信息Map*/
        Map<String, Object> userInfoMap = null;
        UserModel userModel = new UserModel();

        try {
            userInfoMap = jdbcTemplate.queryForMap(SQLAccess.SelectUserInfoWithThirdPartOpenidAndroidVersion, new Object[]{openid});
        } catch (EmptyResultDataAccessException exception) {
            LOGGER.error("根据第三方openid获取用户信息错误,没有此用户");
            return null;
        }


        // 设置用户关注分类信息新格式
        userModel.setUserFocusTypeIds(JSONObject.parseObject((String) userInfoMap.get("userFocusId")).getJSONArray("focusList"));


        userModel.setUserId((int) userInfoMap.get("userId"));
        userModel.setUserName((String) userInfoMap.get("userName"));
        userModel.setUserPhoto((String) userInfoMap.get("userPhoto"));
        userModel.setUserSex((String) userInfoMap.get("userSex"));
        userModel.setUserCollectedNum((int) userInfoMap.get("userCollectNumber"));
        userModel.setTokenRY((String) userInfoMap.get("token"));
        userModel.setSchool((String) userInfoMap.get("school"));
        userModel.setSchoolYear((int) userInfoMap.get("schoolYear"));
        userModel.setHeight(((BigDecimal) userInfoMap.get("height")).intValue());
        userModel.setWeight(((BigDecimal) userInfoMap.get("weight")).doubleValue());

        return userModel;
    }

    /**
     * 搜索学校
     *
     * @param schoolKey
     */
    @Override
    public List<Map<String, Object>> searchSchool(String schoolKey) {
        String param = "'%" + schoolKey + "%'";
        List<Map<String, Object>> schoolMapList = jdbcTemplate.queryForList("SELECT schoolName,schoolLocation FROM school_info WHERE schoolName LIKE " + param);
        return schoolMapList;
    }

    /**
     * 获取用户参与活动信息
     *
     * @param userId
     */
    @Override
    public String getUserJoinedActivityIds(int userId) {
        try {
            return jdbcTemplate.queryForObject(SQLAccess.SelectUserJoinActivityInfo, new Object[]{userId}, java.lang.String.class);
        } catch (EmptyResultDataAccessException exception) {
            return null;
        }
    }

    /**
     * 更新用户参与活动信息
     *
     * @param userId
     * @param activityIds
     */
    @Override
    public boolean updateUserJoinedActivityIds(int userId, JSONArray activityIds) {
        int row = jdbcTemplate.update(SQLAccess.UpdateUserJoinActivityInfo, new Object[]{activityIds.toJSONString(), userId});
        return (row == 1) ? true : false;
    }

    /**
     * 完善用户身高体重信息
     *
     * @param userId
     * @param height
     * @param weight
     */
    @Override
    public boolean setBodyInfo(int userId, double height, double weight, String name, String school) {
        int row = jdbcTemplate.update(SQLAccess.UpdateUserBodyInfo, new Object[]{height, weight, name, school, userId});
        return (row == 1) ? true : false;
    }

    /**
     * 获取用户
     *
     * @param userId
     */
    @Override
    public Map<String, Object> getUserBodyInfo(int userId) {
        try {
            return jdbcTemplate.queryForMap(SQLAccess.SelectUserBodyInfo, new Object[]{userId});
        } catch (EmptyResultDataAccessException exception) {
            LOGGER.error("获取用户身高体重信息错误,未找到用户信息,userId: " + userId);
            Map<String, Object> userBodyInfoMap = new HashMap<>();

            // 查找不到用户身高体重数据,返回默认值0
            userBodyInfoMap.put("height", 0);
            userBodyInfoMap.put("weight", 0);
            return userBodyInfoMap;
        }
    }

    /**
     * 根据第三方参数尝试获取用户信息
     *
     * @param openid
     */
    @Override
    public Map<String, Object> getUserInfoWithThirdPartLogin(String openid, String os) {
        if ("iOS".equals(os)) {
            // iOS版本
            UserModel userModel = getUserInfo(openid);

            if (userModel != null) {
                return userModel.mapSerialize();
            } else {
                return null;
            }
        } else {
            // Android版本
            UserModel userModel = getUserInfoAnroid(openid);

            if (userModel != null) {
                return userModel.mapSerialize();
            } else {
                return null;
            }
        }

    }


    /**
     * 使用第三方平台信息注册
     *
     * @param openid
     * @param token
     * @return
     */
    @Override
    public int registerWithThirdPartLogin(final String openid, final String token, final String uuid) {
        KeyHolder key = new GeneratedKeyHolder();
        jdbcTemplate.update(new PreparedStatementCreator() {
            @Override
            public PreparedStatement createPreparedStatement(Connection conn)
                    throws SQLException {

                PreparedStatement preStatement = conn.prepareStatement(
                        SQLAccess.AddNewUserWithThridPart, Statement.RETURN_GENERATED_KEYS);
                preStatement.setString(1, openid);
                preStatement.setString(2, token);
                preStatement.setString(3, uuid);
                preStatement.setTimestamp(4, new Timestamp(new Date().getTime()));
                return preStatement;
            }
        }, key);
        return key.getKey().intValue();
    }

    @Override
    public Map<String, Object> getUserInfo(int userId) {
        try {
            return jdbcTemplate.queryForMap(SQLAccess.SelectUserInfoOfMap, new Object[]{userId});
        } catch (Exception exception) {
            LOGGER.error("根据userId获取用户信息失败,userId: " + userId);
            return null;
        }
    }

    @Override
    public UserModel freshUserToken(int userId, String token) {
        int row = jdbcTemplate.update(SQLAccess.UpdateUserThirdPartTokenInfo, new Object[]{token, userId});

        if (row == 1) {
            return login(userId, "", "");
        } else {
            LOGGER.error("更新用户token失败,userId: " + userId);
            return null;
        }
    }

    /**
     * 获取用户模块积分
     *
     * @param userId
     * @param module
     * @param action
     */
    @Override
    public int getModuleCoin(int userId, String module, String action) {
        try {
            return jdbcTemplate.queryForObject(SQLAccess.SelectModuleUserCoin, new Object[]{userId, module, action}, java.lang.Integer.class);
        } catch (Exception exception) {
            LOGGER.info("获取用户模块积分记录错误; userId: " + userId + " ,module: " + module + " ,action: " + action, exception);
            return 0;
        }
    }

    /**
     * 获取用户模块积分
     *
     * @param userId
     * @param module
     * @param action
     */
    @Override
    public int getModuleCoinCount(int userId, String module, String action) {
        try {
            return jdbcTemplate.queryForObject(SQLAccess.SelectModuleUserCoinCount, new Object[]{userId, module, action}, java.lang.Integer.class);
        } catch (Exception exception) {
            LOGGER.info("获取用户模块积分总计记录错误,未查找到数据; userId: " + userId + " ,module: " + module + " ,action: " + action);
            return 0;
        }
    }

    /**
     * 增加用户总积分
     *
     * @param userId
     * @param addCoin
     */
    @Override
    public boolean addUserCountCoin(int userId, int addCoin) {
        int row = jdbcTemplate.update(SQLAccess.UpdateUserCountCoin, new Object[]{addCoin, userId});
        return (row == 1) ? true : false;
    }

    /**
     * 获取用户总积分(除跬步公益跑外)
     *
     * @param userId
     */
    @Override
    public int getUserCountCoin(int userId) {
        try {
            Map<String, Object> userCoinMap = jdbcTemplate.queryForMap(SQLAccess.SelectUserCountCoin, new Object[]{userId});
            int userCoin = (int) userCoinMap.get("userCoin");
            int userShareAppCoin = (int) userCoinMap.get("userShareAppCoin");
            int userCompleteInfoCoin = (int) userCoinMap.get("userCompleteInfoCoin");

            return userCoin + userShareAppCoin + userCompleteInfoCoin; // 把用户分享所获积分,完善个人信息积分也算在用户积分里面
        } catch (Exception exception) {
            return 0;
        }
    }

    @Override
    public int getUserDaysCoinCount(int userId) {
        // 每日积分: 1.阅读文章; 2.收藏文章; 3.文章评论; 4.文章分享; 5.文章点赞; 6.活动打卡; 7.活动打卡分享

        int readArticleCoinCount = getModuleCoinCount(userId, "information", "readArticle"); // 1. 阅读文章总积分
        int collectArticleCoinCount = getModuleCoinCount(userId, "information", "collectArticle"); // 2. 收藏文章积分
        int articleCommentCoinCount = getModuleCoinCount(userId, "information", "commentInPageOrReply"); // 3. 文章评论积分
        int shareArticleCoinCount = getModuleCoinCount(userId, "information", "shareArticle"); // 4. 分享文章积分
        int articlePraiseCoinCount = getModuleCoinCount(userId, "information", "goodOrBadArticle"); // 5. 文章点赞积分

        int activityLaunchCardCoin = activityDao.getUserLaunchCardCoinCount(userId); // 6. 活动打卡积分
        int activityShareCoinCount = activityDao.getActivityShareCoinCount(userId); // 7. 活动分享积分
        return readArticleCoinCount + collectArticleCoinCount + articleCommentCoinCount + shareArticleCoinCount + articlePraiseCoinCount + activityLaunchCardCoin + activityShareCoinCount;

    }


}
